package network;

import java.io.UnsupportedEncodingException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;



public class Packet {

	public enum packettype {BASE,MESSAGE,ALIVE,ACKNOWLEDGE,PING,REQUEST,CHUNK,PLAYER,UPDATE,STATE,ACTORS,ACTOR_REQUEST};		
	

	InetAddress m_address;
	int m_timestamp; 
	packettype m_type;

	public Packet(packettype type, int timestamp,InetAddress address)
	{
		m_address=address;
		m_timestamp=timestamp;
		m_type=type;
		
	}
	
	public InetAddress getAddress()
	{
		return m_address;		
	}
	
	public int getTimestamp()
	{
		return m_timestamp;	
	}
	
	public packettype getType()
	{
		return m_type;
	}
	
	public Packet()
	{
		
	}
	
	public static byte getTypebyte(packettype type)
	{
		switch (type)
		{
			case MESSAGE:
				return 0;
				
			case ALIVE:
				return 1;
			case PING:
				return 2;
			case REQUEST:
				return 3;
			case CHUNK:
				return 4;
			case PLAYER:
				return 5;
			case UPDATE:
				return 6;
			case STATE:
				return 7;
			case ACTORS:
				return 8;
			case ACTOR_REQUEST:
				return 9;
		}
		return 0;
	}
	
	public static packettype getTypeEnum(byte b)
	{
		switch (b)
		{
		case 0:
			return packettype.MESSAGE;
			
		case 1:
			return packettype.ALIVE;
		case 2:
			return packettype.PING;
		case 3:
			return packettype.REQUEST;
		case 4:
			return packettype.CHUNK;
		case 5:
			return packettype.PLAYER;
		case 6:
			return packettype.UPDATE;
		case 7:
			return packettype.STATE;
		case 8:
			return packettype.ACTORS;
		case 9:
			return packettype.ACTOR_REQUEST;
		}
		return packettype.BASE;
	}
	
	public void Header(InetAddress address, ByteBuffer buffer)
	{
		m_address=address;
		
		byte b=buffer.get();
		m_type=getTypeEnum(b);
		
		buffer.position(1);
		m_timestamp=buffer.getInt();
		
	}
	
	public DatagramPacket Encode(InetAddress address, int port)
	{
		byte []buffer=new byte[1024];
		ByteBuffer BB=ByteBuffer.wrap(buffer);
		//encode type
		BB.put(getTypebyte(m_type));
		BB.putInt(m_timestamp);
		return new DatagramPacket(buffer,buffer.length,address,port);
	}
	
	public Packet(DatagramPacket pack)
	{
		ByteBuffer buffer=ByteBuffer.wrap(pack.getData());
		Header(pack.getAddress(),buffer);			
	}
	
	public static Packet Decode(DatagramPacket packet)
	{
		//extract originating IP
		InetAddress address=packet.getAddress();
		//extract the first character of the buffer
		int b=packet.getData()[0];
		switch (b)
		{
		case 0: //handshake
			return new Packet_Message(packet);

		case 1: //alive
			return new Packet_Alive(packet);
		case 2: //generic
			return new Packet(packet);
		case 3:
			return new Packet_Request(packet);
		
		case 4: 
			return new Packet_Chunk(packet);
		case 5:
			return new Packet_Player(packet);
		case 6:
			return new Packet_Update(packet);
		case 7:
			return new Packet_State(packet);
		case 8:
			return new Packet_Actors(packet);
		case 9:
			return new Packet_ActorRequest(packet);
		}
		return new Packet();
	}
	
	static String ReadString(ByteBuffer buffer)
	{
		//read the first two bytes as a short int
		short length=buffer.getShort();
		
		//now read that many characters out
		byte [] putter= new byte[length];
		for (int i=0;i<length;i++)
		{
			putter[i]=buffer.get();
		}
		String str=new String(putter);
		return str;
	}
	
	static void WriteString(ByteBuffer buffer, String str)
	{
		short l=(short) str.length();
		byte [] putter=new byte[l];
		try {
			putter=str.getBytes("US-ASCII");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		buffer.putShort(l);
		for (int i=0;i<l;i++)
		{
			buffer.put(putter[i]);
		}
		
	}
	
}
